from Factors.General import *


def FCFToTotalIncomeCallback(dfFundamental, factorName, params):
    #
    type = "_" + params["Type"]
    dfFundamental[factorName] = (dfFundamental["FreeCashFlow" + type] / np.abs(dfFundamental["TotalIncome" + type]))


def FCFROICCallback(dfFundamental, factorName, params):
    #
    # IC = Common Equity(Book Value) + LT Debt + PS + Minority Insterest
    type = "_" + params["Type"]
    dfFundamental[factorName] = dfFundamental["FreeCashFlow" + type] / (dfFundamental["PaidInCapital"] + dfFundamental["LTDebt"] + dfFundamental["MinorityInterest"])


def LTFCFToAsset(dfFundamental, factorName, params):

    # --- 准备一个临时DF，以ReportDate为Index---
    dfTemp = dfFundamental.set_index(['ReportDate'])

    fields = params["Fields"]
    targetField = fields[0]

    year = params["Year"]
    targetPeriod = params["Period"]
    dfFundamental[factorName] = np.nan
    for index, row in dfFundamental.iterrows():
        #
        value = row[targetField]
        #
        period = row["Period"]
        if period != targetPeriod:
            continue

        reportDate = row["ReportDate"]
        # reportDate = index
        currentYear = reportDate.year

        complete = True
        sum = 0
        for back in range(year):
            # ---Find Previous Statement---
            reportDatePrevYear = Gadget.GenerateReportDate(currentYear - back, period, isUTC=False)
            # reportDatePrevYear = pd.to_datetime(reportDatePrevYear)
            reportDatePrevYear = reportDatePrevYear.date()

            #
            if reportDatePrevYear in dfTemp.index:
                previousValue = dfTemp.loc[reportDatePrevYear, targetField]
                sum += previousValue
                #
            else:
                complete = False
                break
        #
        if complete:
            dfFundamental.at[index, factorName] = sum / dfFundamental.at[index, "TotalAsset"]
            # or
            # dfFundamental.loc[index, factorName] = sum / dfFundamental.loc[index, "TotalAsset"]

    # print(dfFundamental.head())
    pass


def CashEarningMinusEarningCallback(dfFundamental, factorName, params):
    #
    type = "_" + params["Type"]
    #
    dfFundamental["Cap"] = dfFundamental["TotalShares"] * dfFundamental["Close"]
    dfFundamental[factorName] = dfFundamental["OperatingCashFlow" + type] / dfFundamental["Cap"] - \
                                dfFundamental["NetIncome2" + type] / dfFundamental["Cap"]


def CashEarningDevideEarningCallback(dfFundamental, factorName, params):
    #
    type = "_" + params["Type"]
    dfFundamental[factorName] = (dfFundamental["OperatingCashFlow" + type] / np.abs(dfFundamental["NetIncome2" + type]))


def CalcCashFlowFactor(database,instruments,datetime1,datetime2,update=False):

    for type in ["LYR", "TTM"]:
        #
        # CalcFundamentalFactor(database, instruments, datetime1, datetime2,
        #                       factorName="FCFToTotalIncome_" + type,
        #                       quarterlyFields=["FreeCashFlow","TotalIncome"],
        #                       callback=FCFToTotalIncomeCallback,
        #                       params={"Type": type},
        #                       update=update)
        #
        # CalcFundamentalFactor(database, instruments, datetime1, datetime2,
        #                       factorName="CashROIC_" + type,
        #                       fields=["PaidInCapital", "LTDebt", "MinorityInterest"],
        #                       quarterlyFields=["FreeCashFlow"],
        #                       callback=FCFROICCallback,
        #                       params={"Type": type},
        #                       startIndex=407,
        #                       update=update)

        #CashEarnings to Earnings
        CalcFundamentalFactor(database, instruments, datetime1, datetime2,
                              factorName="CashEarningToEarning_" + type,
                              fields=[],
                              quarterlyFields=["OperatingCashFlow", "NetIncome2"],
                              callback=CashEarningDevideEarningCallback,
                              update=False,
                              params={"Type": type})

        CalcFundamentalFactor(database, instruments, datetime1, datetime2,
                              factorName="CashEarningMinusEarning_" + type,
                              fields=["TotalShares","Close"],
                              quarterlyFields=["OperatingCashFlow", "NetIncome2"],
                              callback=CashEarningMinusEarningCallback,
                              params={"Type": type})

    # Only LYR Based
    CalcFundamentalFactor(database, instruments, datetime1, datetime2,
                          factorName="LTFCFToAsset_3Yr",
                          fields=["TotalAsset"],
                          quarterlyFields=["FreeCashFlow"],
                          callback=LTFCFToAsset,
                          params={"Period": 4, "Year": 3, "Type": "LYR"})



